
#include "color.h"

#include <math.h>
#include <assert.h>

void Color_Init(Color* color, unsigned char r, unsigned char g, unsigned char b,unsigned char a)
{
	color->r = r;
	color->g = g;
	color->b = b;
	color->a = a;
}

void Color_Rgb2Hsl(const Color* rgb, HSL* hsl)
{
	HSL var = { _bytetofloat[rgb->r], _bytetofloat[rgb->g], _bytetofloat[rgb->b]};
	HSL del;
    float min = MIN(var.h, var.s);
    float max = MAX(var.h, var.s);
    float delta;
	hsl->a = rgb->a;

	min = MIN(min, var.l );
	max = MAX(max, var.l );
	delta = max - min;

    hsl->l = ( min + max ) / 2;

    if ( delta == 0 )
    {
       hsl->h = 0;
       hsl->s = 0;
    }
    else
    {
       if ( hsl->l < 0.5f )
		   hsl->s = delta / ( max + min );
       else
		   hsl->s = delta / ( 2.0f - max - min );

       del.h = ( ( ( max - hsl->h ) / 6.0f ) + ( max / 2.0f ) ) / delta;
       del.l = ( ( ( max - hsl->s ) / 6.0f ) + ( max / 2.0f ) ) / delta;
       del.s = ( ( ( max - hsl->l ) / 6.0f ) + ( max / 2.0f ) ) / delta;

       if ( hsl->h == max )
		   hsl->h = del.s - del.l;
       else if ( hsl->s == max )
		   hsl->h = ( 1.0f / 3.0f ) + del.h - del.s;
       else if ( hsl->l == max )
		   hsl->h = ( 2.0f / 3.0f ) + del.l - del.h;

       if ( hsl->h < 0 ) {hsl->h += 1;}
       if ( hsl->h > 1 ) {hsl->h -= 1;}
    }
}

void Color_Hsl2Rgb(const HSL* hsl, Color* rgb)
{
	float var_1, var_2;
	rgb->a = hsl->a;
	if ( hsl->s == 0 )
	{
	   rgb->r = (unsigned char)(hsl->l * 255);
	   rgb->g = rgb->r;
	   rgb->b = rgb->r;
	}
	else
	{
	   if ( hsl->l < 0.5 )
		   var_2 = hsl->l * ( 1 + hsl->s );
	   else
		   var_2 = ( hsl->l + hsl->s ) - ( hsl->s * hsl->l );

	   var_1 = 2.0f * hsl->l - var_2;

	   rgb->r = (unsigned char)(255 * Color_HueToRgb( var_1, var_2, hsl->h + ( 0.333333f )));
	   rgb->g = (unsigned char)(255 * Color_HueToRgb( var_1, var_2, hsl->h ));
	   rgb->b = (unsigned char)(255 * Color_HueToRgb( var_1, var_2, hsl->h - ( 0.333333f  )));
	}
}

Color Color_GetHint(const float hint)
{
	Color rgb;
	HSL hsl = {hint,1,0.5f,255};
	Color_Hsl2Rgb(&hsl,&rgb);
	return rgb;
}

Color Color_GetRandomHint()
{
	Color rgb;
	HSL hsl = {(float)(rand() % 360) / 360,1,0.5f,255};
	Color_Hsl2Rgb(&hsl,&rgb);
	return rgb;
}

Color Color_GetBlend(const Color* c1, const Color* c2, float factor)
{
	Color result;
	assert((factor >= 0)  && (factor <= 1));
	result.r = c1->r * (1.0f -factor) + c2->r * factor;
	result.g = c1->g * (1.0f -factor) + c2->g * factor;
	result.b = c1->b * (1.0f -factor) + c2->b * factor;
	result.a = c1->a * (1.0f -factor) + c2->a * factor;
	return result;
}


Color Color_GetHintBlend(const Color* c1, const Color* c2, float factor)
{
	/*Color result;
	HSL _hsl1, _hsl2;
	Color_Rgb2Hsl(c1,&_hsl1);
	Color_Rgb2Hsl(c2,&_hsl2);
	assert((factor >= 0)  && (factor <= 1));
	_hsl1.h = (_hsl1.h * (1.0f - factor)) + (_hsl2.h * factor);
	Color_Hsl2Rgb(&_hsl1,&result);
	return result;*/
	return *c1;
}

static float Color_HueToRgb(float v1,float v2, float vH )
{
   if ( vH < 0  ) vH += 1 ;
   if ( vH > 1  ) vH -= 1 ;
   if ( ( 6  * vH ) < 1  )
	   return v1 + ( v2 - v1 ) * 6  * vH;
   if ( ( 2  * vH ) < 1  )
	   return v2;
   if ( ( 3  * vH ) < 2  )
	   return v1 + ( v2 - v1 ) * ( ( 2 / 3  ) - vH ) * 6 ;
   return v1;
}
